 // MyTesTSuite.h
#include <iostream>             
#include <iterator>
#include <cxxtest/TestSuite.h>
#include <vector>
#include "smatrix/smatrix2.hpp"
#include "elim_subst_inq.hpp"

typedef double coef_t;

#ifdef BOOST_MATRIX

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace boost::numeric::ublas;
typedef matrix<coef_t>  SMatrix;
#endif


#ifndef BOOST_MATRIX
#include "smatrix2.hpp"
using namespace smatrix2;
typedef sparse_matrix2<coef_t> SMatrix;
#endif


using namespace std;


typedef std::vector<coef_t> Vector;

#define DBL_EPSILON 2.2204460492503131E-16

double Round(double v, int decimals){
    int sgn = (int) (v/fabs(v));
    double eps = sgn*pow10(decimals);
    double rmr = fmod( v, eps );
    v -= rmr;
    if( sgn*rmr - sgn*(eps / 2)>-DBL_EPSILON )
	v += eps;
    return v;
}	//double Round(double v, int decimals)

template <class T>
void fill_matrix(T l, SMatrix & sm) {
    for(size_t i=0; i < sm.size1(); ++i)
	for (size_t j=0; j< sm.size2(); ++j)
	    sm(i, j) = l[i][j];
	    //std::copy(l[i], l[i]+sizeof(l[i])/sizeof(coef_t), sm.begind2(i));
	    
}

class TestF_And:  public CxxTest::TestSuite 
{
	public:

        static TestF_And *createSuite() { return new TestF_And; }
        static void destroySuite( TestF_And *suite ) { delete suite; }
			
	TestF_And(){
	}
	virtual ~TestF_And(){ 
	};
// ++++++++++++++++++++++++++++ Suite ++++++++++++++++++++++++++++++++++++++++
	
	void testAlive( void )
	{
	    TS_TRACE( "Suite started" );
	    TS_ASSERT_EQUALS(2+2,4);
	}
	/// x + y  >= 2
	/// x - y  >= 0
	
	void test_01(){
	    TS_TRACE("TEST 01");
	    SMatrix sm(2,2);
	    coef_t l[][2]= {{1,  1},
	                 {1, -1}};
	    coef_t c0[]= {2, 0};
//	    std::copy(l1, l1+sizeof(l1)/sizeof(coef_t), sm.begind2(0));
//	    std::copy(l2, l2+2, sm.begind2(1));
	    fill_matrix(l, sm);
	    Vector c(2);
	    std::copy(c0, c0+2, c.begin());
	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, true);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	}
	
	// x + y >=10
	// -x-y >=-3
	// no solutions
	
	void test_02(){
	    TS_TRACE("TEST 02");
	    SMatrix sm(2,2);
	    coef_t l[][2]={ {1, 1},
		            {-1,-1}};
			    
	    coef_t c0[]= {10, -3};
//	    std::copy(l1, l1+sizeof(l1)/sizeof(coef_t), sm.begind2(0));
//	    std::copy(l2, l2+sizeof(l2)/sizeof(coef_t), sm.begind2(1));
	    fill_matrix(l, sm);
	    
	    Vector c(2);
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	}
	
	
	void test_03() {
	    TS_TRACE("TEST 03");
	    coef_t l [][10] = {
			 {-11, 1,  5,   8, -34, -56,  -3,  0,   23,   8},
			 {1,-1, -3,  45,  44, -1,  -43,  54,  -3,  -1},
			 {-1,-4,  0,   5,  -4,  11,  43,  55,   5,   1},
			 {1,-6, 23,   4,   3,  1,  -4,   75,   8,  -1},
			 {-1, 8, 58,  -45, -3,  0 , -3,  -90, -12,  41},
			 {1, 0, -6,   55, 89, -34,  4,   37,   3,  13},
			 {-1,-1, -3,   5, -32, -90,  3,   44,   0, -15},
			 {1,33, -55,  64,  9, -28,  0,    0,  22, -61},
			 {-1,84, -33, -6,  23,  0,  -5,  -22,  34,   0},
			 {1,-5, -89, -25,  0, -31, -10,   8,  -2, -31}
	    };
	    
	    
	    coef_t c0[]= {2, 0, 23, -4, -18, -45, 34, 22, 33 , 0 };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, true);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	}
	
	void test_04() {
	    
	    TS_TRACE("TEST 04");
	    
	    coef_t l [][10] = {
			 {1, -1,  5,   8, -34, -56,  -3,  0,   23,   8},
			 {-1,-1, -3,  45,  44, -1,  -43,  54,  -3,  -1},
			 {1,-4,  0,   5,  -4,  11,  43,  55,   5,   1},
			 {-1,-6, 23,   4,   3,  1,  -4,   75,   8,  -1},
			 {1, 8, 58,  -45, -3,  0 , -3,  -90, -12,  41},
			 {-1, 0, -6,   55, 89, -34,  4,   37,   3,  13},
			 {1,-1, -3,   5, -32, -90,  3,   44,   0, -15},
			 {1,33, -55,  64,  9, -28,  0,    0,  22, -61},
			 {-1,84, -33, -6,  23,  0,  -5,  -22,  34,   0},
			 {-1, 1,  -5,   -8, 34, 56,  3,  0,   -23,   -8},
	    };
	    
	    ///falce      \/                                     \/ 
	    coef_t c0[]= {10, 0, 23, -4, -18, -45, 34, 22, -33 , 2 };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	}
	
	void xtest_05() {
	    
	    TS_TRACE("TEST 05");    
	
	    coef_t l [][10] = {
			 {1, -1,  5,   8, -34, -56,  -3,  0,   23,   8},
			 
			 {-1,-1, -3,  45,  44, -1,  -43,  54,  -3,  -1},
			 {1,-4,  0,   5,  -4,  11,  43,  55,   5,   1},
			 {-1,-6, 23,   4,   3,  1,  -4,   75,   8,  -1},
			 
			 {-1, 1,  -5,   -8, 34, 56,  3,  0,   -23,   -8},
			 
			 {1, 8, 58,  -45, -3,  0 , -3,  -90, -12,  41},
			 {-1, 0, -6,   55, 89, -34,  4,   37,   3,  13},
			 {1,-1, -3,   5, -32, -90,  3,   44,   0, -15},
			 {1,33, -55,  64,  9, -28,  0,    0,  22, -61},
			 {-1,84, -33, -6,  23,  0,  -5,  -22,  34,   0},
			 
	    };
	    
	    ///falce      \/              \/                        
	    coef_t c0[]= {10, 0, 23, -4,  2, -18, -45, 34, 22, -33 };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	}
	 
	// 2       1       -1
	// 0       0.5     0.5
	// 0       0       -1
	// 8 1 1
	//expected result 2 3 -1
	void test_06() {
	    
	    TS_TRACE("TEST 06");
	    coef_t l [][3] = {
			 {2,	1,	-1},
			 {1,	0.5,	0.5},
			 {-2,	-1,	1}
			 
	    };
	    
	    ///falce       \/    \/                        
	    coef_t c0[]= { 8, 1, 1 };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
//	    TS_ASSERT_EQUALS((int)Round(c[1]/sm(1, 1), -1 ), 1); // = 1
	} 
//	-1      5       -7      6
//	9       -2       3      -1
//	-1      8       -4      -8
//	3       -4      3       56
//	23 0 -5 -22

	void test_07() {
	    
	    TS_TRACE("TEST 07");
	    coef_t l [][4] = {
		{-1,      5,       -7,      6},
		{1,       -5,      7,       -6},
		{9,       -2,       3,      -1},
		{-1,      8,       -4,      -8}
//		{3,       -4,      3,       56}
	        

			 
	    };
//	    Solution[4](1.29534,-4.31064,-6.89339,-0.400864)
	    ///false      \/          \/                        
	    coef_t c0[]= {23, -22, 0, -5  };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    
	    fill_matrix(l, sm);	   
	    	   
	   Vector c(sizeof(c0)/sizeof(coef_t));
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    TS_ASSERT_EQUALS(res.nbrunches, 12);
	    
	}
	
	void test_08(){
	    TS_TRACE("TEST 08");
	    SMatrix sm(2,2);
	    coef_t l [][2] = {
			      {1, 1},
			      {1,-1}
			     };
	    coef_t c0[] = {2, 0};
	    
	    fill_matrix(l, sm);	
	    
	    Vector c(2);
	    std::copy(c0, c0+2, c.begin());
	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubstLEq <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, true);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    TS_ASSERT_EQUALS(res.nbrunches, 0);
	    
	} 
	void test_09() {
	    
	    TS_TRACE("TEST 09");
	    coef_t l [][3] = {
			 {2,	1,	-1},
			 {1,	0.5,	0.5},
			 {-2,	-1,	1}
			 
	    };
	    
	    ///falce       \/    \/                        
	    coef_t c0[]= { 1, 1, -8 };
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubstLEq <SMatrix, Vector> solver (sm,c);

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    TS_ASSERT_EQUALS(res.nbrunches, 3);
	    
	} 
	
	void test_10() {
	    
	    TS_TRACE("TEST 10");
	    coef_t l [][2] = {
			 {1,	1},
			 {-1,	1},
			 {1,	-1},
			 {-1,	-1}
			 
	    };
	    
	    /// l <= c0                      
	    coef_t c0[]= { 1, 1, 1, 1};
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	    fill_matrix(l, sm);	   	   

	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubstLEq <SMatrix, Vector> solver (sm,c); // <=

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, true);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches "<<res.nbrunches<<endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    
	    TS_ASSERT_EQUALS(res.nbrunches, 0);
	    
	}
	
	void test_11() {
	    
	    TS_TRACE("TEST 11");
	    coef_t l [][2] = {
			 {1,	1},
			 {-1,	1},
			 {1,	-1},
			 {-1,	-1}
			 
	    };
	    
	    /// l >= c0                      
	    coef_t c0[]= { 1, 1, 1, 1};
	    
	    size_t n_of_lines = sizeof(l)/sizeof(*l);
	    
	    assert(sizeof(c0)/sizeof(coef_t) == n_of_lines );
	    
	    SMatrix sm(n_of_lines, sizeof(l[0])/sizeof(coef_t));
	   
	   
	    fill_matrix(l, sm);
	    
	    Vector c(sizeof(c0)/sizeof(coef_t));
	    
	    std::copy(c0, c0+sizeof(c0)/sizeof(coef_t), c.begin());

	    cout<<"\nInput matrix"<< sm<<endl;
	    cout<<"\nInput vector ";
	    std::copy(c.begin(), c.end(), std::ostream_iterator<coef_t>(cout, " "));
	    

	    InqSolverSubst <SMatrix, Vector> solver (sm,c); // >=

	    InqSolverResult res = solver.Solve();

	    TS_ASSERT_EQUALS(res.consistent, false);
	    cout<< (res.consistent ? "\nproved":"\nrefuted");
	    
	    cout<<"\nBrunches " << res.nbrunches << endl;
	    cout<<"\nSubs made: "<< res.nsolved << endl;
	    TS_ASSERT_EQUALS(res.nbrunches, 4);
	    
	} 
	
	
};
